package com.funsport.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.funsport.common.enums.EventStatus;
import com.funsport.entity.*;
import com.funsport.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 推荐服务实现
 * 提供活动推荐、用户推荐、俱乐部推荐等功能
 *
 * @author Fun-Sport Team
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RecommendationServiceImpl implements IRecommendationService {

    private final IUserService userService;
    private final IEventService eventService;
    private final IClubService clubService;
    private final IEventSignupService eventSignupService;
    private final IClubMemberService clubMemberService;

    @Override
    public List<Event> recommendEventsForUser(Long userId, Integer limit) {
        User user = userService.getById(userId);
        if (user == null) {
            log.warn("用户不存在: userId={}", userId);
            return Collections.emptyList();
        }

        if (limit == null || limit <= 0) {
            limit = 10;
        }

        // 基础查询：未来的、已发布的、公开的活动
        LambdaQueryWrapper<Event> baseQuery = new LambdaQueryWrapper<Event>()
                .eq(Event::getStatus, EventStatus.PUBLISHED)
                .gt(Event::getStartTime, LocalDateTime.now())
                .and(wrapper -> wrapper.eq(Event::getIsPublic, true).or().isNull(Event::getIsPublic))
                .orderByDesc(Event::getStartTime);

        // 用户已报名的活动ID
        List<EventSignup> signedEvents = eventSignupService.list(
                new LambdaQueryWrapper<EventSignup>()
                        .eq(EventSignup::getUserId, userId)
                        .in(EventSignup::getStatus, Arrays.asList("confirmed", "attended"))
        );
        Set<Long> signedEventIds = signedEvents.stream()
                .map(EventSignup::getEventId)
                .collect(Collectors.toSet());

        // 排除已报名的活动
        if (!signedEventIds.isEmpty()) {
            baseQuery.notIn(Event::getId, signedEventIds);
        }

        List<Event> recommended = new ArrayList<>();
        Set<Long> seenIds = new HashSet<>();

        // 策略1：用户加入的俱乐部的活动（优先级最高）
        List<ClubMember> userClubs = clubMemberService.list(
                new LambdaQueryWrapper<ClubMember>()
                        .eq(ClubMember::getUserId, userId)
                        .eq(ClubMember::getStatus, "active")
        );
        
        if (!userClubs.isEmpty()) {
            Set<Long> clubIds = userClubs.stream()
                    .map(ClubMember::getClubId)
                    .collect(Collectors.toSet());

            LambdaQueryWrapper<Event> clubQuery = new LambdaQueryWrapper<Event>()
                    .eq(Event::getStatus, EventStatus.PUBLISHED)
                    .gt(Event::getStartTime, LocalDateTime.now())
                    .and(wrapper -> wrapper.eq(Event::getIsPublic, true).or().isNull(Event::getIsPublic))
                    .in(Event::getClubId, clubIds)
                    .orderByDesc(Event::getStartTime);
            
            if (!signedEventIds.isEmpty()) {
                clubQuery.notIn(Event::getId, signedEventIds);
            }
            
            List<Event> clubEvents = eventService.list(clubQuery);

            for (Event event : clubEvents) {
                if (seenIds.size() >= limit) break;
                if (!seenIds.contains(event.getId())) {
                    recommended.add(event);
                    seenIds.add(event.getId());
                }
            }
        }

        // 策略2：同城市的热门活动
        if (seenIds.size() < limit && user.getCity() != null) {
            LambdaQueryWrapper<Event> cityQuery = new LambdaQueryWrapper<Event>()
                    .eq(Event::getStatus, EventStatus.PUBLISHED)
                    .gt(Event::getStartTime, LocalDateTime.now())
                    .and(wrapper -> wrapper.eq(Event::getIsPublic, true).or().isNull(Event::getIsPublic))
                    .eq(Event::getCity, user.getCity())
                    .orderByDesc(Event::getCurrentParticipants)
                    .orderByDesc(Event::getStartTime)
                    .last("LIMIT " + (limit - seenIds.size()));
            
            if (!signedEventIds.isEmpty()) {
                cityQuery.notIn(Event::getId, signedEventIds);
            }
            
            List<Event> cityEvents = eventService.list(cityQuery);

            for (Event event : cityEvents) {
                if (seenIds.size() >= limit) break;
                if (!seenIds.contains(event.getId())) {
                    recommended.add(event);
                    seenIds.add(event.getId());
                }
            }
        }

        // 策略3：热门活动（按报名人数排序）
        if (seenIds.size() < limit) {
            LambdaQueryWrapper<Event> popularQuery = new LambdaQueryWrapper<Event>()
                    .eq(Event::getStatus, EventStatus.PUBLISHED)
                    .gt(Event::getStartTime, LocalDateTime.now())
                    .and(wrapper -> wrapper.eq(Event::getIsPublic, true).or().isNull(Event::getIsPublic))
                    .orderByDesc(Event::getCurrentParticipants)
                    .orderByDesc(Event::getStartTime)
                    .last("LIMIT " + (limit - seenIds.size()));
            
            if (!signedEventIds.isEmpty()) {
                popularQuery.notIn(Event::getId, signedEventIds);
            }
            
            List<Event> popularEvents = eventService.list(popularQuery);

            for (Event event : popularEvents) {
                if (seenIds.size() >= limit) break;
                if (!seenIds.contains(event.getId())) {
                    recommended.add(event);
                    seenIds.add(event.getId());
                }
            }
        }

        log.info("为用户推荐活动: userId={}, 推荐数量={}", userId, recommended.size());
        return recommended;
    }

    @Override
    public List<Club> recommendClubsForUser(Long userId, Integer limit) {
        User user = userService.getById(userId);
        if (user == null) {
            log.warn("用户不存在: userId={}", userId);
            return Collections.emptyList();
        }

        if (limit == null || limit <= 0) {
            limit = 10;
        }

        // 基础查询：活跃状态的俱乐部
        LambdaQueryWrapper<Club> baseQuery = new LambdaQueryWrapper<Club>()
                .eq(Club::getStatus, "active");

        // 用户已加入的俱乐部ID
        List<ClubMember> joinedClubs = clubMemberService.list(
                new LambdaQueryWrapper<ClubMember>()
                        .eq(ClubMember::getUserId, userId)
                        .eq(ClubMember::getStatus, "active")
        );
        Set<Long> joinedClubIds = joinedClubs.stream()
                .map(ClubMember::getClubId)
                .collect(Collectors.toSet());

        // 排除已加入的俱乐部
        if (!joinedClubIds.isEmpty()) {
            baseQuery.notIn(Club::getId, joinedClubIds);
        }

        List<Club> recommended = new ArrayList<>();
        Set<Long> seenIds = new HashSet<>();

        // 策略1：同城市的俱乐部（优先级最高）
        if (user.getCity() != null) {
            List<Club> cityClubs = clubService.list(
                    baseQuery.clone()
                            .eq(Club::getCity, user.getCity())
                            .orderByDesc(Club::getCurrentMembers)
                            .last("LIMIT " + limit)
            );

            for (Club club : cityClubs) {
                if (seenIds.size() >= limit) break;
                if (!seenIds.contains(club.getId())) {
                    recommended.add(club);
                    seenIds.add(club.getId());
                }
            }
        }

        // 策略2：活跃度高的俱乐部（按等级和成员数）
        if (seenIds.size() < limit) {
            List<Club> activeClubs = clubService.list(
                    baseQuery.clone()
                            .orderByDesc(Club::getLevel)
                            .orderByDesc(Club::getCurrentMembers)
                            .last("LIMIT " + (limit - seenIds.size()))
            );

            for (Club club : activeClubs) {
                if (seenIds.size() >= limit) break;
                if (!seenIds.contains(club.getId())) {
                    recommended.add(club);
                    seenIds.add(club.getId());
                }
            }
        }

        log.info("为用户推荐俱乐部: userId={}, 推荐数量={}", userId, recommended.size());
        return recommended;
    }

    @Override
    public List<User> recommendUsersForUser(Long userId, Integer limit) {
        User user = userService.getById(userId);
        if (user == null) {
            log.warn("用户不存在: userId={}", userId);
            return Collections.emptyList();
        }

        if (limit == null || limit <= 0) {
            limit = 10;
        }

        List<User> recommended = new ArrayList<>();
        Set<Long> seenIds = new HashSet<>();
        seenIds.add(userId); // 排除自己

        // 策略1：同俱乐部成员（优先级最高）
        List<ClubMember> userClubs = clubMemberService.list(
                new LambdaQueryWrapper<ClubMember>()
                        .eq(ClubMember::getUserId, userId)
                        .eq(ClubMember::getStatus, "active")
        );

        if (!userClubs.isEmpty()) {
            Set<Long> clubIds = userClubs.stream()
                    .map(ClubMember::getClubId)
                    .collect(Collectors.toSet());

            List<ClubMember> clubMembers = clubMemberService.list(
                    new LambdaQueryWrapper<ClubMember>()
                            .in(ClubMember::getClubId, clubIds)
                            .ne(ClubMember::getUserId, userId)
                            .eq(ClubMember::getStatus, "active")
            );

            Set<Long> memberIds = clubMembers.stream()
                    .map(ClubMember::getUserId)
                    .collect(Collectors.toSet());

            if (!memberIds.isEmpty()) {
                List<User> clubUsers = userService.listByIds(memberIds);
                for (User u : clubUsers) {
                    if (seenIds.size() >= limit + 1) break; // +1因为包含自己
                    if (!seenIds.contains(u.getId())) {
                        recommended.add(u);
                        seenIds.add(u.getId());
                    }
                }
            }
        }

        // 策略2：同城市用户
        if (user.getCity() != null && seenIds.size() < limit + 1) {
            List<User> cityUsers = userService.list(
                    new LambdaQueryWrapper<User>()
                            .eq(User::getCity, user.getCity())
                            .ne(User::getId, userId)
                            .eq(User::getStatus, "active")
                            .last("LIMIT " + (limit - seenIds.size() + 1))
            );

            for (User u : cityUsers) {
                if (seenIds.size() >= limit + 1) break;
                if (!seenIds.contains(u.getId())) {
                    recommended.add(u);
                    seenIds.add(u.getId());
                }
            }
        }

        log.info("为用户推荐好友: userId={}, 推荐数量={}", userId, recommended.size());
        return recommended;
    }

    @Override
    public List<Map<String, Object>> getHotEvents(String city, Integer days, Integer limit) {
        if (days == null || days <= 0) {
            days = 7;
        }
        if (limit == null || limit <= 0) {
            limit = 10;
        }

        LocalDateTime endTime = LocalDateTime.now().plusDays(days);

        LambdaQueryWrapper<Event> query = new LambdaQueryWrapper<Event>()
                .eq(Event::getStatus, EventStatus.PUBLISHED.name())
                .gt(Event::getStartTime, LocalDateTime.now())
                .lt(Event::getStartTime, endTime);

        // Event实体没有city字段，暂时移除城市过滤
        // if (city != null && !city.isEmpty()) {
        //     query.like(Event::getLocationName, city);
        // }

        List<Event> events = eventService.list(
                query.orderByDesc(Event::getCurrentParticipants)
                        .last("LIMIT " + limit)
        );

        List<Map<String, Object>> result = new ArrayList<>();
        for (Event event : events) {
            Map<String, Object> item = new HashMap<>();
            item.put("event", event);

            // 计算报名率
            double signupRate = 0;
            if (event.getMaxParticipants() != null && event.getMaxParticipants() > 0) {
                signupRate = (double) event.getCurrentParticipants() / event.getMaxParticipants() * 100;
            }
            item.put("signupRate", Math.round(signupRate * 10.0) / 10.0);
            item.put("isHot", signupRate > 80);

            result.add(item);
        }

        log.info("获取热门活动: city={}, days={}, 数量={}", city, days, result.size());
        return result;
    }

    @Override
    public List<Event> getSimilarEvents(Long eventId, Integer limit) {
        Event event = eventService.getById(eventId);
        if (event == null) {
            log.warn("活动不存在: eventId={}", eventId);
            return Collections.emptyList();
        }

        if (limit == null || limit <= 0) {
            limit = 5;
        }

        // 相似条件：同运动类型、未来的活动
        List<Event> similarEvents = eventService.list(
                new LambdaQueryWrapper<Event>()
                        .ne(Event::getId, eventId)
                        .eq(Event::getSportTypeId, event.getSportTypeId())
                        .eq(Event::getStatus, EventStatus.PUBLISHED.name())
                        .gt(Event::getStartTime, LocalDateTime.now())
                        .orderByDesc(Event::getStartTime)
                        .last("LIMIT " + limit)
        );

        log.info("获取相似活动: eventId={}, 数量={}", eventId, similarEvents.size());
        return similarEvents;
    }
}

